package org.richin.support.orm.spring;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.transform.Transformers;
import org.richin.lang.util.Convert;
import org.richin.lang.util.StringUtils;
import org.richin.support.orm.IPageDAO;
import org.richin.support.orm.Page;
import org.springframework.util.Assert;
import org.springside.modules.orm.PropertyFilter;


/**
 * 分页DAO类 需要分页的DAOl类继承这个类
 * 
 * @author Administrator
 * 
 * @param <T>
 * @param <ID>
 */
public abstract class PageSpringDao<T, ID extends Serializable> extends SpringDaoSupportImp<T, ID> implements
		IPageDAO<T, ID> {

	@SuppressWarnings("unchecked")
	public Page<T> find(Page<T> page, String queryString, Object... values) {
		Assert.notNull(page);
		Query query = createQuery(queryString, values);
		setPageParameter(query, page);
		List<T> result = query.list();
		page.setResult(result);
		return page;
	}

	@SuppressWarnings("unchecked")
	public Page<T> findBySql(Page<T> page, String queryString, Map<String, Object> values) {
		Assert.notNull(page);
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.aliasToBean(typeClass()));
		setPageParameter(query, page);
		
		List<T> result = query.list();
		page.setResult(result);
		return page;
	}
	@SuppressWarnings("unchecked")
	public Page findBySql(Page page, String queryString, Map<String, Object> values,Class entityClass) {
		Assert.notNull(page);
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.aliasToBean(entityClass));
		setPageParameter(query, page);
		page.setResult(query.list());
		return page;
	}

	@SuppressWarnings("unchecked")
	public Page<T> findBySql(Page<T> page, String queryString, Object... values) {
		Assert.notNull(page);
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.aliasToBean(typeClass()));
		setPageParameter(query, page);
		List<T> result = query.list();
		page.setResult(result);
		return page;
	}

	public Page<T> find(Page<T> page, List<PropertyFilter> filters) {
		Criterion[] criterions = buildFilterCriterions(filters);
		return findByCriteria(page, criterions);
	}
	@SuppressWarnings("unchecked")
	public Page<T> findByNamedQuery(Page<T> page,String queryName,Object...values) {
		Assert.notNull(page);
		Query query = getNamedQuery(queryName, values);
		String queryString=query.getQueryString();
		queryString=StringUtils.replaceBetween(queryString, " count(*) ", "select", "from");
		int totalCount=Convert.castToNumber(findUnique(queryString, values)).intValue();
		setPageParameter(query, page);
		List<T> result = query.list();
		page.setResult(result);
		page.setTotalCount(totalCount);
		return page;
	}

	public Page<T> findByCriteria(Page<T> page, Criterion... criterions) {
		Assert.notNull(page, "page不能为空");

		Criteria c = createCriteria(criterions);

		if (page.isAutoCount()) {
			int totalCount = countCriteriaResult(c);
			page.setTotalCount(totalCount);
		}
		if (isCacheable())
			c.setCacheable(true);
		setPageParameter(c, page);
		List<T> result = c.list();
		page.setResult(result);
		return page;
	}

	public List<T> findByProperty(String propertyName, Object value, String matchTypeStr) {
		// TODO Auto-generated method stub
		return null;
	}

	public Page<T> getAll(Page<T> page) {
		return findByCriteria(page, new Criterion[0]);
	}

	protected Criteria setPageParameter(Criteria c, Page<T> page) {
		String[] orderByArray;
		String[] orderArray;
		int i;
		c.setFirstResult(page.getFirst());
		c.setMaxResults(page.getPageSize());

		if (page.isOrderBySetted()) {
			orderByArray = StringUtils.split(page.getOrderBy(), ',');
			orderArray = StringUtils.split(page.getOrder(), ',');

			Assert.isTrue(orderByArray.length == orderArray.length, "分页多重排序参数中,排序字段与排序方向的个数不相等");

			for (i = 0; i < orderByArray.length; ++i)
				if ("asc".equals(orderArray[i]))
					c.addOrder(Order.asc(orderByArray[i]));
				else
					c.addOrder(Order.desc(orderByArray[i]));

		}

		return c;
	}

	protected Query setPageParameter(Query query, Page<T> page) {
		query.setFirstResult(page.getFirst());
		query.setMaxResults(page.getPageSize());
		return query;
	}

	public abstract void setSuperSessionFactory(SessionFactory sessionFactory);
}
